package com.puff.web.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.puff.core.Puff;
import com.puff.exception.ErrorHandler;
import com.puff.log.Log;
import com.puff.log.LogFactory;
import com.puff.web.view.View;

public class ControllerDispatcher extends Dispatcher {

	private static final Log log = LogFactory.get(ControllerDispatcher.class);
	private static final ErrorHandler errorHandler = Puff.getErrorHandler();

	@Override
	public void dispatching(String target, HttpServletRequest request, HttpServletResponse response, ExecutorProvider provider) {
		PuffContext context = null;
		Executor executor = null;
		View view = null;
		try {
			context = PuffContext.init(request, response);
			executor = provider.getExecutor(request, target);
			if (executor == null) {
				view = errorHandler.handle404();
			} else {
				context.setExecutor(executor.executorKey, executor);
				DispatcherExecutor dispatcher = new DispatcherExecutor(executor);
				long start = System.currentTimeMillis();
				dispatcher.execute();
				view = dispatcher.getResult();
				if (Puff.getDevMode()) {
					dispatcher.executorReport(start);
				}
			}
		} catch (Throwable e) {
			log.error("Puff handle the controller '{0}' hanpend error", e, target);
			view = executor.handleExecption(e);
		} finally {
			if (view != null) {
				try {
					view.view();
				} catch (Exception e) {
					log.error("Puff View '{0}' hanpend error", e, executor.executorKey);
					errorHandler.handleExecption(executor, e).view();
				}
			}
			if (context != null) {
				context.remove();
			}
		}
	}

}